#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <mutex>
#include <list>
#include <mutex>
#include <algorithm>
#include <memory>
#include <atomic>
#include <assert.h>

using namespace std;

// Disable copy from lvalue.
//unique_ptr(const unique_ptr&) = delete;
//unique_ptr& operator=(const unique_ptr&) = delete;

// 自定义对象
class Test
{
public:
    Test(const string &str=string())
    {
//        cout << "Create Test" << endl;
        std::cout <<__PRETTY_FUNCTION__ << endl;
        m_str = string("test") + str;
    }
    ~Test()
    {
//        cout << "~Del Test()" << endl;
        std::cout <<__PRETTY_FUNCTION__ << endl;
    }

    string m_str;
};

class Son
{
public:
    Son(const string &str=string(), int num=0): m_str(std::move(str)) , m_num(num)
    {
        std::cout <<__PRETTY_FUNCTION__ << endl;
        m_unptr.reset(new Test(str));
    }

    ~Son()
    {
        std::cout <<__PRETTY_FUNCTION__ << endl;
    }

    string m_str = string();
    int m_num = 0;
    unique_ptr<Test> m_unptr;
};


class Absobj
{
public:
    Absobj()
    {
        printf("Create Abs - address: %p\n", this);
        for ( int i=0; i<3; i++ )
        {
            unique_ptr<int> ptr(new int);                       // 不能传递栈上的变量， 否在智能对象在释放时会释放无效对象
            vptr.push_back(std::move(ptr));
        }

        for ( int i=0; i<3; i++ )
        {
            unique_ptr<string> ptr(new string(std::to_string(i)));          // 不能传递栈上的变量， 否在智能对象在释放时会释放无效对象
            vsptr.push_back(std::move(ptr));
        }
    }

    void print()
    {
        printf("Absobj print------\n");
        for ( auto &obj: vsptr )
        {
            printf("str: %s \n", obj.get()->c_str());
        }
    }

    ~Absobj()
    {
        printf("~Del AbsObj - address: %p\n", this);
    }


    void add()
    {
        for( int i=0; i<3; i++)
        {
            unique_ptr<Son> pson(new Son());
            svptr.push_back(std::move(pson));
        }
        printf("svptr.size: %d\n", (int)svptr.size());
    }

    char *pBuf = nullptr;
    int m_num = 0;

    vector<unique_ptr<int>> vptr;
    vector<unique_ptr<string>> vsptr;
    vector<unique_ptr<Son>> svptr;
};


unique_ptr<Absobj> createPoint(int num)
{
    unique_ptr<Absobj> ptr(new Absobj);
    printf("ptr: %p\n", &ptr);
    ptr->m_num = num;
    return ptr;
}

void printAbsNum(const Absobj &abs)
{
    std::cout <<"abs.num: " << abs.m_num;
}

void dowork(std::unique_ptr<Absobj> &&ptr)
{
    printf("ptr: %d\n", ptr->m_num);
    ptr->m_num = 888;
}

void towork(std::unique_ptr<Absobj> &ptr)
{
    printf(">>>ptr: %d\n", ptr->m_num);
    ptr->m_num = 999;
}

void gowork(std::unique_ptr<Absobj> ptr)
{
    printf("-->ptr: %d\n", ptr->m_num);
}

vector<unique_ptr<Absobj>> pushwork()
{
    vector<unique_ptr<Absobj>> vec;
    for ( int i=0; i<3; i++ )
    {
        unique_ptr<Absobj> pAbs(new Absobj);
        pAbs->m_num = i;
        vec.push_back(std::move(pAbs));
    }
    return vec;
}


/**
 * @brief The DataMng class         增删改查
 */
class DataMng
{
public:
    DataMng(){}

    void add(const string &str, int num)
    {
        m_uniptrVec.push_back(unique_ptr<Son>(new Son(str, num)));
    }

    // 根据条件删除指定的对象
    void del(int num)
    {
        for ( auto iter = m_uniptrVec.begin(); iter != m_uniptrVec.end(); )
        {
            if ( (*iter).get() == nullptr )
                continue;

            if ( (*iter)->m_num == num )
            {
                printf("earse address: %p | num: %d | str: %s\n", (*iter).get(), (*iter)->m_num, (*iter)->m_str.c_str());
                iter = m_uniptrVec.erase(iter);
            }else
            {
                iter++;
            }
        }
    }

    // 直接删除指定对象
    void del(unique_ptr<Son> &ptr)
    {
        auto iter = std::find(m_uniptrVec.begin(),m_uniptrVec.end(), ptr);
        if ( iter != m_uniptrVec.end() )
        {
            printf("del.\n");
            iter = m_uniptrVec.erase((iter));
        }
    }

    // 删除全部数据
    void del()
    {
        auto iter = m_uniptrVec.begin();
        while( iter != m_uniptrVec.end() )
        {
            iter = m_uniptrVec.erase(iter);
        }
    }

    // 更新数据
    void update(int num, const string &str)
    {
        for ( auto iter = m_uniptrVec.begin(); iter != m_uniptrVec.end(); )
        {
            if ( (*iter).get() == nullptr )
                continue;
            if ( (*iter)->m_num == num )
            {
                (*iter)->m_str = str;
                (*iter)->m_unptr->m_str= str;
                break;
            }else{
                iter++;
            }
        }
    }

    // 根据条件查找智能指针对象的裸指针(返回裸指针, 有风险)
    Son *find(int num)
    {
        for ( auto iter = m_uniptrVec.begin(); iter != m_uniptrVec.end(); )
        {
            if ( (*iter).get() == nullptr )
                continue;
            if ( (*iter)->m_num == num )
            {
                return (*iter).get();           // 返回裸指针, 有风险
            }else{
                iter++;
            }
        }
        return nullptr;
    }

    // 智能指针容器
    vector<unique_ptr<Son>> &uniptrVec()
    {
        return m_uniptrVec;
    }

    // 打印信息
    void printVec()
    {
        for ( auto &obj: m_uniptrVec )
        {
            printf("address: %p | num: %d | str: %s | tstr: %s\n", obj.get(), obj->m_num, obj->m_str.c_str(), obj->m_unptr.get()->m_str.c_str());
        }
        printf("\n");
    }

private:
    vector<unique_ptr<Son>> m_uniptrVec;
};


/**
 * @brief main              智能指针测试
 * @return
 */
int main(void)
{
    DataMng dataMng;
    printf(">>>>>>>>>>>>>>>>Add\n");
    // 增
    for (int i=0; i<4; i++)
    {
        dataMng.add(std::to_string(i), i);
    }
    dataMng.printVec();

    // 改
    printf(">>>>>>>>>>>>>>>>Changed\n");
    dataMng.update(2, string("88888888"));
    dataMng.printVec();

    // 查
    printf(">>>>>>>>>>>>>>>>Find\n");
    auto ptr = dataMng.find(2);
    printf("find ptr: %p | num: %d | str: %s\n", &ptr, ptr->m_num, ptr->m_str.c_str());
    dataMng.update(ptr->m_num, string("22222222"));
    dataMng.update(1, string("1111111111111"));
    dataMng.printVec();

    // 删
    printf(">>>>>>>>>>>>>>>>Del\n");
    dataMng.del(dataMng.uniptrVec()[0]);
    dataMng.printVec();

    dataMng.del(1);
    dataMng.printVec();

    printf("End uniptrVec.size: %d\n", (int)dataMng.uniptrVec().size());
    printf("\n");

    vector<unique_ptr<Absobj>> absUniVec;
    for (int i=0; i<3; i++)
    {
        unique_ptr<Absobj> absPtr;
        absUniVec.push_back(std::move(absPtr));
    }

    // 异常 (不能将同一个裸指针赋值给不同的智能指针, 因为最后对象析构后, 会重复析构两次裸指针)
    int *pInt = new int[32];
    unique_ptr<int> iptr(pInt);
//    unique_ptr<int> iiptr(pInt);                // 错误，会导致最后二次释放
    unique_ptr<int> iiptr(iptr.release());        // 正确, 转移裸指针的控制权，自动删除对象
    return 0;
}



